<?php
# ***** BEGIN LICENSE BLOCK *****
# This file is part of "myWiWall".
# Copyright (c) 2007 CRP Henri Tudor and contributors.
# All rights reserved.
#
# "myWiWall" is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
# 
# "myWiWall" is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with "myWiWall"; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# ***** END LICENSE BLOCK *****

/**
* @package palette.php.inc
* @author Laurent Haan <laurent.haan@gmail.com>
*/

class REST
{
	
/* This contains the data passed to the REST Web service */
private $input;

/* The response XML document */
private $doc;

/* The four methods */
private $methods;

	function __construct()
	{
		$this->input = file_get_contents('php://input');
		$this->doc = new DOMDocument('1.0', 'UTF-8');
		$this->doc->formatOutput = true;
	}
	
	/**
	 * This method is used to determine what HTTP method REST is used with 
	 */
	private function getHttpMethod()
	{
		return strtoupper($_SERVER['REQUEST_METHOD']);
	}
	
	/**
	 * This method lets you register a function to one of the four HTTP methods
	 * @param string action This should be one of the four methods put, get, post or delete
	 * @param function func This should be a valid callback function
	 */
	function registerAction($action, $func)
	{
		$this->methods[strtolower($action)] = $func;
	}
	
	/**
	 * This method lets you access the arguments of the REST service
	 */
	function getArgument($i)
	{
		$val = explode('/', substr($_SERVER['PATH_INFO'], 1));
 		return $val[$i];
	}
	
	/**
	 * This method lets you specify the HTTP return code
	 */
	private function setReturnCode($code)
	{
		/* set the error code in the response HTTP header */
	 	header("HTTP/1.0 $code");
	}
	
	/**
	 * This function returns a HTTP response with the correct status code,
	 * containing the XML document with the response status and content
	 */
	function generateResponse($content, $code, $namespace = null, $error = 0)
	{
	 	/* set the error code in the response HTTP header */
	 	$this->setReturnCode($code);
	 	
	 	$root = $this->doc->createElementNS($namespace, 'response');
	 	$root =  $this->doc->appendChild($root);
	 	
		$status = $this->doc->createElement('error');
		$status->nodeValue = $error;
		$status = $root->appendChild($status);
		
		$root->appendChild($content);
	
	 	echo $this->doc->saveXML();
	}
	 
	/**
	 * This function wraps generateResponse() to return error messages
	 */
	function generateError($msg, $code, $ns = null)
	{
		$message = new DOMElement('message', $msg);
		$this->generateResponse($message, $code, $ns, 1);
	}
	  
	/**
	 * This function wraps generateResponse() to return success messages
	 */
	function generateSuccess($msg, $code, $ns = null)
	{
		$message = new DOMElement('message', $msg);
		$this->generateResponse($message, $code, $ns, 0);
	}

	/**
	 * This function creates an absolute URI for a resource
	 */
	function generateURI($resource)
	{
	 	$array = explode('/', $_SERVER['PHP_SELF']);
	 	array_pop($array);
	 	array_pop($array);
	 	return 'http://' . $_SERVER['HTTP_HOST'] . implode('/', $array) . '/' . $resource;
	}
	
	/**
	 * This function gives you access to the parsed and validated input DOMDocument
	 */
	function getInputDOM($schema = null)
	{
	 	/* Enable user error handling */
	 	libxml_use_internal_errors(true);
	 	
	 	$doc = new DOMDocument();
	 	$doc->preserveWhiteSpace = false;
	 	
	 	/* load the XML Schema using our own Error Handler */
	 	if(!@$doc->loadXML($this->input))
	 	{
	 		$message = ": ";
	 		$errors = libxml_get_errors();
	 		foreach ($errors as $error) {
	 			$message .= "(" . $error->code . ")" . trim($error->message) . " on line " . $error->line . "; ";
			}
			libxml_clear_errors();
			
			/* there is a problem with the XML, throw a 400 BAD REQUEST*/
	 		throw new Exception(XML_PARSE_ERROR . $message, 400);
	 	}
	 	
	 	/* validate the XML Schema using our own Error Handler */
	 	if(isset($schema) && !@$doc->schemaValidate($schema))
	 	{
	 		$message = ": ";
	 		$errors = libxml_get_errors();
	 		foreach ($errors as $error) {
	 			$message .= "(" . $error->code . ")" . trim($error->message) . " on line " . $error->line . "; ";
			}
			libxml_clear_errors();
			
			/* there is a problem with the XML, throw a 400 BAD REQUEST*/
	 		throw new Exception(XML_VALIDATE_ERROR . $message, 400);
	 	}
	 	
	 	return $doc;
	}
	
	/**
	 * This function gives you access to the result DOMDocument
	 */
	function getResultDOM()
	{
		return $this->doc;
	}

	/**
	 * This executes the main body of the REST service
	 */
	function run()
	{

		if(isset($this->methods[strtolower($this->getHttpMethod())]))
			call_user_func($this->methods[strtolower($this->getHttpMethod())]);
		
		else
			throw new Exception('No defined function found for method ' .  $this->getHttpMethod(), 400);
	}
}
?>